package org.geekbang.projects.config;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.spi.ConfigBuilder;
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
* 通用的配置生产解析器  
* @author : KangNing Hu
*/
public class CommonConfigProviderResolver extends ConfigProviderResolver {

	private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

	private Map<ClassLoader , Config> configMap = new HashMap<>();


	@Override
	public Config getConfig() {
		return getConfig(Thread.currentThread().getContextClassLoader());
	}



	@Override
	public Config getConfig(ClassLoader classLoader) {
		ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
		ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
		try {
			readLock.lock();
			Config config = configMap.get(classLoader);
			if (config != null){
				return config;
			}
		}finally {
			readLock.unlock();
		}
		Config config;
		try {
			writeLock.lock();
			config = new DefaultConfigBuilder()
					//添加默认配置源
					.addDefaultSources()
					//添加第三方配置源
					.addDiscoveredSources()
					//添加转换器
					.addDiscoveredConverters()
					//构建对象
					.build();
			configMap.put(classLoader , config);
		}finally {
			writeLock.unlock();
		}
		return config;
	}


	@Override
	public ConfigBuilder getBuilder() {
		return new DefaultConfigBuilder();
	}



	@Override
	public void registerConfig(Config config, ClassLoader classLoader) {
		ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
		try {
			writeLock.lock();
			configMap.put(classLoader , config);
		}finally {
			writeLock.unlock();
		}
	}



	@Override
	public void releaseConfig(Config config) {
		ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
		writeLock.lock();
		try {
			for (Map.Entry<ClassLoader , Config> entry : configMap.entrySet()){
				if (entry.getValue() == config){
					configMap.remove(entry.getKey());
				}
			}
		}finally {
			writeLock.unlock();
		}
	}
}
